

#include "CXMLWriter.h"
#include <wchar.h>
#include "irrString.h"

namespace irr
{
    namespace io
    {


        //! Constructor
        CXMLWriter::CXMLWriter(IWriteFile* file)
            : File(file)
        {
            if (File)
                File->grab();
        }



        //! Destructor
        CXMLWriter::~CXMLWriter()
        {
            if (File)
                File->drop();
        }



        //! Writes a xml 1.0 header like <?xml version="1.0"?>
        void CXMLWriter::writeXMLHeader()
        {
            if (!File)
                return;

            u16 h = 0xFEFF;
            File->write(&h, 2);

            wchar_t* p = L"<?xml version=\"1.0\"?>";
            File->write(p, wcslen(p)*2);

            writeLineBreak();
        }



        //! Writes an xml element with maximal 5 attributes
        void CXMLWriter::writeElement(const wchar_t* name, bool empty,
            const wchar_t* attr1Name, const wchar_t* attr1Value,
            const wchar_t* attr2Name, const wchar_t* attr2Value,
            const wchar_t* attr3Name, const wchar_t* attr3Value,
            const wchar_t* attr4Name, const wchar_t* attr4Value,
            const wchar_t* attr5Name, const wchar_t* attr5Value)
        {
            if (!File || !name)
                return;

            // write name

            File->write(L"<", 2);
            File->write(name, wcslen(name)*2);

            // write attributes

            writeAttribute(attr1Name, attr1Value);
            writeAttribute(attr2Name, attr2Value);
            writeAttribute(attr3Name, attr3Value);
            writeAttribute(attr4Name, attr4Value);
            writeAttribute(attr5Name, attr5Value);

            // write closing tag
            if (empty)
                File->write(L" />", 6);
            else
                File->write(L">", 2);
        }


        void CXMLWriter::writeAttribute(const wchar_t* name, const wchar_t* value)
        {
            if (!name || !value)
                return;

            File->write(L" ", 2);
            File->write(name, wcslen(name)*2);
            File->write(L"=\"", 4);
            File->write(value, wcslen(value)*2); // TODO: replace special characters
            File->write(L"\"", 2);
        }


        //! Writes a comment into the xml file
        void CXMLWriter::writeComment(const wchar_t* comment)
        {
            if (!File || !comment)
                return;

            File->write(L"<!--", 8);
            File->write(comment, wcslen(comment)*2); // TODO: replace special characters
            File->write(L"-->", 6);
        }


        //! Writes the closing tag for an element. Like </foo>
        void CXMLWriter::writeClosingTag(const wchar_t* name)
        {
            if (!File || !name)
                return;

            File->write(L"</", 4);
            File->write(name, wcslen(name)*2);
            File->write(L">", 2);
        }



        const CXMLWriter::XMLSpecialCharacters XMLWSChar[] =
        {
            { L'&', L"&amp;" },
            { L'<', L"&lt;" },
            { L'>', L"&gt;" },
            { L'"', L"&quot;" },
            { L'\0', 0}
        };


        //! Writes a text into the file. All occurrences of special characters like
        //! & (&amp;), < (&lt;), > (&gt;), and " (&quot;) are automaticly replaced.
        void CXMLWriter::writeText(const wchar_t* text)
        {
            if (!File || !text)
                return;

            core::stringw s;
            const wchar_t* p = text;

            while(*p)
            {
                // check if it is matching
                bool found = false;
                for (s32 i=0; XMLWSChar[i].Character != '\0'; ++i)
                    if (*p == XMLWSChar[i].Character)
                    {
                        s.append(XMLWSChar[i].Symbol);
                        found = true;
                        break;
                    }

                    if (!found)
                        s.append(*p);
                    ++p;
            }

            // write new string
            File->write(s.c_str(), s.size()*2);
        }


        //! Writes a line break
        void CXMLWriter::writeLineBreak()
        {
            if (!File)
                return;

            File->write("\n", 2);
        }


    } // end namespace irr
} // end namespace io

